问题
常用的实现Singleton有两种方式,都是将构造器私有,然后通过导出public的静态域。一种是通过public的静态final成员变量实现:
public class Singleton{ public static final Singleton instance = new Singleton(); private Singleton(){ ...... } }
缺点:这种方式,可以通过反射改变构造器的私有属性,创建多个实例对象,这样需要在构造方法中加入逻辑判断不允许创建第二个实例。
还有一种方式,是通过导出public的静态方法:
class Singleton{ private static final Singleton instance = new Singleton(); public static Singleton getInstance(){ return instance; } private Singleton(){}; }
但是还是存在第1种方法里的反射机制进行攻击的问题。以上两种方法还有一个问题,就是在实现Singleton类序列化的时候,仅仅在声名中加上“implement Serializable”是不够的。为了维护并保证Singleton,必须声名所有的实例都是transient,并提供一个readResolve方法。否则的话每次反序列化的时候都会创建一个新的实例,这个时候要加入以下代码:
// readResolve method to preserve singleton property private Object readResolve() { // Return the one true Elvis and let the garbage collector // take care of the Elvis impersonator return INSTANCE; }
那么,构建Singleton最简单安全可靠的方式是什么?
解决
实现Singleton最安全可靠的方式,可以编写包含单个元素的枚举元素:
public enum Elvis { INSTANCE; public void leaveTheBuilding() { ... } }
这种方法更加简洁,无偿的提供了序列化机制,绝对防止多次实例化(由Enum保证),即使是在面对复杂的序列化或者反序列化或者反射攻击的时候也可以保证唯一。这已成为实现 Singleton的最佳方法。
结论
但需要创建Singleton时,可以使用枚举的方式实现,这种实现方式既简洁又能保证序列化安全和反射安全。